#include <windows.h>
#include "image.h"
#include "api.h"

typedef struct tagBITMAPINFO2 { // bmi 
   BITMAPINFOHEADER bmiHeader; 
   RGBQUAD          bmiColors[256];
} BITMAPINFO2;

void imageBitmapInfo(BITMAPINFO2 *bi, PIMAGEHEADER header){
	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bi->bmiHeader.biBitCount = 24;
	bi->bmiHeader.biWidth = header->dx;
	bi->bmiHeader.biHeight = header->dy;
	bi->bmiHeader.biPlanes = 1;
	bi->bmiHeader.biCompression = BI_RGB;
	int i;
	for(i=0;i<256;i++){
		bi->bmiColors[i].rgbRed = 0;
		bi->bmiColors[i].rgbGreen = 0;
		bi->bmiColors[i].rgbBlue = 0;
	}
}

void imageCreateBitmap(PIMAGE image, PIMAGEHEADER header){
	BITMAPINFO2 bi;
	imageBitmapInfo(&bi, header);
	image->hBitmap = CreateDIBSection(GetWindowDC(NULL), (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&image->mem, NULL, 0);
	image->dx = header->dx;
	image->dy = header->dy;
	image->line = (((24*image->dx + 31) & (~31))>>3);
	// Make the bitmap with white
	int total = image->line * image->dy;
	memset(image->mem, 0xFF, total);
}

void imageDelete(PIMAGE image){
	DeleteObject(image->hBitmap);
	FREE_VALUE(image);
}

PIMAGE imageCreate(int dx, int dy){
	NEW_VALUE(IMAGE, image);
	IMAGEHEADER header = {24, dx, dy, 0};
	imageCreateBitmap(image, &header);
	return image;
}

PIMAGE imageLoader(char *fileName, IMAGE_CALLBACK loader){
	int i;
	PBYTE ptr;
	IMAGEHEADER header;
	memset(&header, 0, sizeof(IMAGEHEADER));
	PVOID handler = (PVOID)loader(IMAGE_LOADER_CREATEHANDLER, NULL, NULL);
	loader(IMAGE_LOADER_OPENIMAGE, handler, fileName);
	loader(IMAGE_LOADER_LOADHEADER, handler, &header);

	if (!header.error){	
		NEW_VALUE(IMAGE, image);

		imageCreateBitmap(image, &header);

		if (header.flg&IMAGE_FLG_UPTODOWN){
			// From Up to Down
			ptr = image->mem + image->line*image->dy;
			for(i=0;i<image->dy;i++){
				ptr -= image->line;
				loader(IMAGE_LOADER_SCANLINE, handler, ptr);
			}
		}
		else{
			// From Down to Up
			ptr = image->mem;
			for(i=0;i<image->dy;i++){			
				loader(IMAGE_LOADER_SCANLINE, handler, ptr);
				ptr += image->line;
			}
		}
		loader(IMAGE_LOADER_CLOSEIMAGE, handler, NULL);
		loader(IMAGE_LOADER_DELETEHANDLER, handler, NULL);
		return image;
	}
	return NULL;
}

void imageSaver(PIMAGE image, char *fileName, IMAGE_CALLBACK saver){
	int i;
	PBYTE ptr;
	IMAGEHEADER header = {24, image->dx, image->dy, 0};
	PVOID handler = (PVOID)saver(IMAGE_SAVER_CREATEHANDLER, NULL, &header);
	saver(IMAGE_SAVER_CREATEIMAGE, handler, fileName);
	saver(IMAGE_SAVER_SAVEHEADER, handler, NULL);

	ptr = image->mem + image->line*image->dy;
	for(i=0;i<image->dy;i++){
		ptr -= image->line;
		saver(IMAGE_LOADER_SCANLINE, handler, ptr);
	}

	saver(IMAGE_SAVER_CLOSEIMAGE, handler, NULL);
	saver(IMAGE_SAVER_DELETEHANDLER, handler, NULL);
}

